/**
 * 
 * 最佳实践
 *   任何在初始化后不应修改且其初始值设定项在编译时已知的变量都应声明为constexpr.
 *   任何在初始化后不应修改且其初始值设定项在编译时未知的变量都应声明为const.
 *   注意：将来我们将讨论一些当前不兼容的类型constexpr（包括std::string、std::vector和其他使用动态内存分配的类型）。对于这些类型的常量对象，使用const。
 * 
 * Const 和 constexpr 函数参数
 *   普通函数调用在运行时进行评估，提供的参数用于初始化函数的参数。这意味着const函数参数被视为运行时常量，即使提供的参数是编译时常量。
 *   由于 constexpr 对象必须使用编译时常量（而不是运行时常量）进行初始化，因此函数参数不能声明为constexpr.
 * 
 */

#include <iostream>

int five()
{
    return 5;
}

int main() {
    int x { 5 };       // not const at all
    const int y { x }; // obviously a runtime const (since initializer is non-const)
    const int z { 5 }; // obviously a compile-time const (since initializer is a constant expression)
    // const int w { getValue() }; // not obvious whether this is a runtime or compile-time const


    constexpr double gravity { 9.8 }; // ok: 9.8 is a constant expression
    constexpr int sum { 4 + 5 };      // ok: 4 + 5 is a constant expression
    constexpr int something { sum };  // ok: sum is a constant expression

    std::cout << "Enter your age: ";
    int age{};
    std::cin >> age;

    // constexpr int myAge { age };      // compile error: age is not a constant expression
    // constexpr int f { five() };       // compile error: return value of five() is not a constant expression

    constexpr int kg{100};

    return 0;
}